﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

namespace ShiQuan.Hanker
{
    /// <summary>
    /// 海康DVR辅助对象
    /// </summary>
    public class HikDVRHelper
    {
        /// <summary>
        /// 初始
        /// </summary>
        /// <returns></returns>
        public static bool DVR_Init()
        {
            var result = HCNetSDK.NET_DVR_Init();
            if (result)
                HCNetSDK.NET_DVR_SetLogToFile(3, "SdkLog", true);
            return result;
        }
        /// <summary>
        /// 设备登录
        /// </summary>
        /// <param name="dvrIp"></param>
        /// <param name="dvrPort"></param>
        /// <param name="userName"></param>
        /// <param name="password"></param>
        /// <param name="msg"></param>
        /// <returns></returns>
        public static int Login(string dvrIp, int dvrPort, string userName, string password,ref HCNetSDK.NET_DVR_DEVICEINFO_V30 mDeviceInfo, out string msg)
        {
            msg = string.Empty;
            //HCNetSDK.NET_DVR_DEVICEINFO_V30 mDeviceInfo = new HCNetSDK.NET_DVR_DEVICEINFO_V30();
            var userId = HCNetSDK.NET_DVR_Login_V30(dvrIp, dvrPort, userName, password, ref mDeviceInfo);
            if(userId < 0)
            {
                var iLastErr = HikDVRHelper.GetLastError();
                msg = "NET_DVR_Login_V30 failed, error code= " + iLastErr; //登录失败，输出错误号
                return userId;
            }

            return userId;
        }
        /// <summary>
        /// 获取通过信息
        /// </summary>
        /// <param name="userId"></param>
        /// <param name="mDeviceInfo"></param>
        /// <param name="listChannel"></param>
        /// <param name="msg"></param>
        /// <returns></returns>
        public static bool GetChannelList(int userId, HCNetSDK.NET_DVR_DEVICEINFO_V30 mDeviceInfo, HCNetSDK.NET_DVR_IPPARACFG_V40 ipParaCfgV40, out List<ChannelInfo> listChannel, out string msg)
        {
            msg = string.Empty;
            listChannel = new List<ChannelInfo>();
            uint dwDChanTotalNum = (uint)mDeviceInfo.byIPChanNum + 256 * (uint)mDeviceInfo.byHighDChanNum;

            if (dwDChanTotalNum > 0)
            {
                uint dwSize = (uint)Marshal.SizeOf(ipParaCfgV40);

                IntPtr ptrIpParaCfgV40 = Marshal.AllocHGlobal((Int32)dwSize);
                Marshal.StructureToPtr(ipParaCfgV40, ptrIpParaCfgV40, false);
                try
                {
                    uint dwReturn = 0;
                    int iGroupNo = 0;  //该Demo仅获取第一组64个通道，如果设备IP通道大于64路，需要按组号0~i多次调用NET_DVR_GET_IPPARACFG_V40获取

                    if (!HCNetSDK.NET_DVR_GetDVRConfig(userId, HCNetSDK.NET_DVR_GET_IPPARACFG_V40, iGroupNo, ptrIpParaCfgV40, dwSize, ref dwReturn))
                    {
                        var iLastErr = HCNetSDK.NET_DVR_GetLastError();
                        msg = "NET_DVR_GET_IPPARACFG_V40 failed, error code= " + iLastErr;
                        //获取IP通道信息失败，输出错误号 Failed to Get IP Channel info and output the error code
                        //MessageBox.Show(strErr);
                        return false;
                    }

                    ipParaCfgV40 = (HCNetSDK.NET_DVR_IPPARACFG_V40)Marshal.PtrToStructure(ptrIpParaCfgV40, typeof(HCNetSDK.NET_DVR_IPPARACFG_V40));

                    //获取可用的模拟通道
                    for (int i = 0; i < ipParaCfgV40.dwAChanNum; i++)
                    {
                        if (ipParaCfgV40.byAnalogChanEnable[i] == 1)
                        {
                            var str = String.Format("通道{0}", i + 1);
                            //comboBoxChan.Items.Add(str);
                            //m_struChanNoInfo.lChannelNo[j] = i + m_struDeviceInfo.byStartChan;
                            listChannel.Add(new ChannelInfo(i + mDeviceInfo.byStartChan, str));
                        }
                    }

                    //获取前64个IP通道中的在线通道
                    uint iDChanNum = 64;

                    if (dwDChanTotalNum < 64)
                    {
                        iDChanNum = dwDChanTotalNum; //如果设备IP通道小于64路，按实际路数获取
                    }

                    byte byStreamType;
                    for (int i = 0; i < iDChanNum; i++)
                    {
                        byStreamType = ipParaCfgV40.struStreamMode[i].byGetStreamType;
                        HCNetSDK.NET_DVR_STREAM_MODE m_struStreamMode = new HCNetSDK.NET_DVR_STREAM_MODE();
                        dwSize = (uint)Marshal.SizeOf(m_struStreamMode);

                        ChannelInfo mChannelInfo = new ChannelInfo();
                        //comboBoxStreamType.SelectedIndex = m_struIPParaCfgV40.struStreamMode[iChanIndex].byGetStreamType;//取流方式/
                        mChannelInfo.StreamType = byStreamType;
                        
                        switch (byStreamType)
                        {
                            //0- 直接从设备取流 0- get stream from device directly
                            case 0:
                                IntPtr ptrChanInfo = Marshal.AllocHGlobal((Int32)dwSize);
                                Marshal.StructureToPtr(ipParaCfgV40.struStreamMode[i].uGetStream, ptrChanInfo, false);
                                HCNetSDK.NET_DVR_IPCHANINFO m_struChanInfo = new HCNetSDK.NET_DVR_IPCHANINFO();
                                m_struChanInfo = (HCNetSDK.NET_DVR_IPCHANINFO)Marshal.PtrToStructure(ptrChanInfo, typeof(HCNetSDK.NET_DVR_IPCHANINFO));

                                //列出IP通道 List the IP channel
                                if (m_struChanInfo.byEnable == 1)
                                {
                                    var str = String.Format("IP通道{0}", i + 1);
                                    //comboBoxChan.Items.Add(str);
                                    //m_struChanNoInfo.lChannelNo[j] = i + (int)m_struIpParaCfgV40.dwStartDChan;
                                    mChannelInfo.ChannelIndex = i + (int)ipParaCfgV40.dwStartDChan;
                                    mChannelInfo.ChannelName = str;
                                    mChannelInfo.IPIndex = m_struChanInfo.byIPID + m_struChanInfo.byIPIDHigh * 256 - iGroupNo * 64 - 1;
                                    mChannelInfo.ChannelNo = Convert.ToString(m_struChanInfo.byChannel);

                                    mChannelInfo.IPAddress = ipParaCfgV40.struIPDevInfo[mChannelInfo.IPIndex].struIP.sIpV4;//前端设备IP地址
                                    mChannelInfo.DVRPort = Convert.ToString(ipParaCfgV40.struIPDevInfo[mChannelInfo.IPIndex].wDVRPort);//前端设备端口
                                    mChannelInfo.UserName = ipParaCfgV40.struIPDevInfo[mChannelInfo.IPIndex].sUserName;//前端设备用户名
                                    mChannelInfo.Password = ipParaCfgV40.struIPDevInfo[mChannelInfo.IPIndex].sPassword;//前端设备密码
                                    mChannelInfo.ProType = ipParaCfgV40.struIPDevInfo[mChannelInfo.IPIndex].byProType;
                                    listChannel.Add(mChannelInfo);
                                }
                                Marshal.FreeHGlobal(ptrChanInfo);
                                break;
                            case 4:
                                IntPtr ptrStreamURL = Marshal.AllocHGlobal((Int32)dwSize);
                                Marshal.StructureToPtr(ipParaCfgV40.struStreamMode[i].uGetStream, ptrStreamURL, false);
                                var m_struStreamURL = (HCNetSDK.NET_DVR_PU_STREAM_URL)Marshal.PtrToStructure(ptrStreamURL, typeof(HCNetSDK.NET_DVR_PU_STREAM_URL));

                                //列出IP通道 List the IP channel
                                //ListIPChannel(i + 1, m_struStreamURL.byEnable, m_struStreamURL.wIPID);
                                //iIPDevID[i] = m_struStreamURL.wIPID - iGroupNo * 64 - 1;
                                if (m_struStreamURL.byEnable == 1)
                                {
                                    var str = String.Format("IP通道{0}", i + 1);
                                    //comboBoxChan.Items.Add(str);
                                    //m_struChanNoInfo.lChannelNo[j] = i + (int)m_struIpParaCfgV40.dwStartDChan;
                                    var ip = m_struStreamURL.wIPID - iGroupNo * 64 - 1;

                                    mChannelInfo.ChannelIndex = i + (int)ipParaCfgV40.dwStartDChan;
                                    mChannelInfo.ChannelName = String.Format("IP通道{0}", i + 1);
                                    mChannelInfo.IPIndex = m_struStreamURL.wIPID - iGroupNo * 64 - 1;

                                    mChannelInfo.IPAddress = ipParaCfgV40.struIPDevInfo[mChannelInfo.IPIndex].struIP.sIpV4;//前端设备IP地址
                                    mChannelInfo.DVRPort = Convert.ToString(ipParaCfgV40.struIPDevInfo[mChannelInfo.IPIndex].wDVRPort);//前端设备端口
                                    mChannelInfo.UserName = ipParaCfgV40.struIPDevInfo[mChannelInfo.IPIndex].sUserName;//前端设备用户名
                                    mChannelInfo.Password = ipParaCfgV40.struIPDevInfo[mChannelInfo.IPIndex].sPassword;//前端设备密码
                                    mChannelInfo.ProType = ipParaCfgV40.struIPDevInfo[mChannelInfo.IPIndex].byProType;
                                    listChannel.Add(mChannelInfo);
                                }

                                Marshal.FreeHGlobal(ptrStreamURL);
                                break;
                            //6- 直接从设备取流扩展 6- get stream from device directly(extended)
                            case 6:
                                IntPtr ptrChanInfoV40 = Marshal.AllocHGlobal((Int32)dwSize);
                                Marshal.StructureToPtr(ipParaCfgV40.struStreamMode[i].uGetStream, ptrChanInfoV40, false);
                                HCNetSDK.NET_DVR_IPCHANINFO_V40 m_struChanInfoV40 = new HCNetSDK.NET_DVR_IPCHANINFO_V40();
                                m_struChanInfoV40 = (HCNetSDK.NET_DVR_IPCHANINFO_V40)Marshal.PtrToStructure(ptrChanInfoV40, typeof(HCNetSDK.NET_DVR_IPCHANINFO_V40));

                                //列出IP通道 List the IP channel
                                if (m_struChanInfoV40.byEnable == 1)
                                {
                                    var str = String.Format("IP通道{0}", i + 1);
                                    //comboBoxChan.Items.Add(str);
                                    //m_struChanNoInfo.lChannelNo[j] = i + (int)m_struIpParaCfgV40.dwStartDChan;
                                    mChannelInfo.ChannelIndex = i + (int)ipParaCfgV40.dwStartDChan;
                                    mChannelInfo.ChannelName = String.Format("IP通道{0}", i + 1);
                                    mChannelInfo.IPIndex =  m_struChanInfoV40.wIPID - iGroupNo * 64 - 1;

                                    mChannelInfo.IPAddress = ipParaCfgV40.struIPDevInfo[mChannelInfo.IPIndex].struIP.sIpV4;//前端设备IP地址
                                    mChannelInfo.DVRPort = Convert.ToString(ipParaCfgV40.struIPDevInfo[mChannelInfo.IPIndex].wDVRPort);//前端设备端口
                                    mChannelInfo.UserName = ipParaCfgV40.struIPDevInfo[mChannelInfo.IPIndex].sUserName;//前端设备用户名
                                    mChannelInfo.Password = ipParaCfgV40.struIPDevInfo[mChannelInfo.IPIndex].sPassword;//前端设备密码
                                    mChannelInfo.ProType = ipParaCfgV40.struIPDevInfo[mChannelInfo.IPIndex].byProType;

                                    mChannelInfo.TransMode = m_struChanInfoV40.byTransMode;
                                    mChannelInfo.TransProtocol = m_struChanInfoV40.byTransProtocol;
                                    listChannel.Add(mChannelInfo);
                                }
                                Marshal.FreeHGlobal(ptrChanInfoV40);
                                break;
                            default:
                                break;
                        }
                    }
                }
                finally
                {
                    Marshal.FreeHGlobal(ptrIpParaCfgV40);
                }
            }
            else
            {
                for (int i = 0; i < mDeviceInfo.byChanNum; i++)
                {
                    var str = String.Format("通道{0}", i + 1);
                    //comboBoxChan.Items.Add(str);
                    //m_struChanNoInfo.lChannelNo[j] = i + m_struDeviceInfo.byStartChan;
                    listChannel.Add(new ChannelInfo(i + mDeviceInfo.byStartChan, str));
                }
            }
            return true;
        }
        /// <summary>
        /// 获取设备信息
        /// </summary>
        /// <param name="userId"></param>
        /// <param name="deviceInfo"></param>
        /// <param name="msg"></param>
        /// <returns></returns>
        public static bool GetDeviceInfo(int userId,ref DeviceInfo deviceInfo,out string msg)
        {
            msg = string.Empty;
            HCNetSDK.NET_DVR_DEVICECFG_V40 m_struDeviceCfg = new HCNetSDK.NET_DVR_DEVICECFG_V40();
            UInt32 dwReturn = 0;
            Int32 nSize = Marshal.SizeOf(m_struDeviceCfg);
            IntPtr ptrDeviceCfg = Marshal.AllocHGlobal(nSize);
            Marshal.StructureToPtr(m_struDeviceCfg, ptrDeviceCfg, false);
            if (!HCNetSDK.NET_DVR_GetDVRConfig(userId, HCNetSDK.NET_DVR_GET_DEVICECFG_V40, -1, ptrDeviceCfg, (UInt32)nSize, ref dwReturn))
            {
                var iLastErr = HCNetSDK.NET_DVR_GetLastError();
                msg = "NET_DVR_GET_DEVICECFG_V40 failed, error code= " + iLastErr;
                //获取设备参数失败，输出错误号 Failed to get the basic parameters of device and output the error code
                //MessageBox.Show(strErr);
                Marshal.FreeHGlobal(ptrDeviceCfg);
                return false;
            }
            
            m_struDeviceCfg = (HCNetSDK.NET_DVR_DEVICECFG_V40)Marshal.PtrToStructure(ptrDeviceCfg, typeof(HCNetSDK.NET_DVR_DEVICECFG_V40));

            deviceInfo.Name = System.Text.Encoding.GetEncoding("GBK").GetString(m_struDeviceCfg.sDVRName);
            deviceInfo.Type = System.Text.Encoding.UTF8.GetString(m_struDeviceCfg.byDevTypeName);
            deviceInfo.AnalogChannel = Convert.ToString(m_struDeviceCfg.byChanNum);
            deviceInfo.IPChannel = Convert.ToString(m_struDeviceCfg.byIPChanNum + 256 * m_struDeviceCfg.byHighIPChanNum);
            deviceInfo.ZeroChannel = Convert.ToString(m_struDeviceCfg.byZeroChanNum);
            deviceInfo.NetworkPort = Convert.ToString(m_struDeviceCfg.byNetworkPortNum);
            deviceInfo.AlarmIn = Convert.ToString(m_struDeviceCfg.byAlarmInPortNum);
            deviceInfo.AlarmOut = Convert.ToString(m_struDeviceCfg.byAlarmOutPortNum);
            deviceInfo.SerialNumber = System.Text.Encoding.UTF8.GetString(m_struDeviceCfg.sSerialNumber);

            uint iVer1 = (m_struDeviceCfg.dwSoftwareVersion >> 24) & 0xFF;
            uint iVer2 = (m_struDeviceCfg.dwSoftwareVersion >> 16) & 0xFF;
            uint iVer3 = m_struDeviceCfg.dwSoftwareVersion & 0xFFFF;
            uint iVer4 = (m_struDeviceCfg.dwSoftwareBuildDate >> 16) & 0xFFFF;
            uint iVer5 = (m_struDeviceCfg.dwSoftwareBuildDate >> 8) & 0xFF;
            uint iVer6 = m_struDeviceCfg.dwSoftwareBuildDate & 0xFF;

            deviceInfo.Version = "V" + iVer1 + "." + iVer2 + "." + iVer3 + " Build " + string.Format("{0:D2}", iVer4) + string.Format("{0:D2}", iVer5) + string.Format("{0:D2}", iVer6);
            
            Marshal.FreeHGlobal(ptrDeviceCfg);
            return true;
        }
        /// <summary>
        /// 获取设备网络信息
        /// </summary>
        /// <param name="userId"></param>
        /// <param name="deviceInfo"></param>
        /// <param name="msg"></param>
        /// <returns></returns>
        public static bool GetNetworkInfo(int userId,ref DeviceInfo deviceInfo,out string msg)
        {
            msg = string.Empty;
            HCNetSDK.NET_DVR_NETCFG_V30 m_struNetCfg = new HCNetSDK.NET_DVR_NETCFG_V30();
            UInt32 dwReturn = 0;
            Int32 nSize = Marshal.SizeOf(m_struNetCfg);
            IntPtr ptrNetCfg = Marshal.AllocHGlobal(nSize);
            Marshal.StructureToPtr(m_struNetCfg, ptrNetCfg, false);

            if (!HCNetSDK.NET_DVR_GetDVRConfig(userId, HCNetSDK.NET_DVR_GET_NETCFG_V30, -1, ptrNetCfg, (UInt32)nSize, ref dwReturn))
            {
                var iLastErr = HCNetSDK.NET_DVR_GetLastError();
                msg = "NET_DVR_GET_NETCFG_V30 failed, error code= " + iLastErr;
                //获取网络参数失败，输出错误号 Failed to get the network parameters and output the error code
                //MessageBox.Show(strErr);
                Marshal.FreeHGlobal(ptrNetCfg);
                return false;
            }
            m_struNetCfg = (HCNetSDK.NET_DVR_NETCFG_V30)Marshal.PtrToStructure(ptrNetCfg, typeof(HCNetSDK.NET_DVR_NETCFG_V30));
            deviceInfo.DVRIP = m_struNetCfg.struEtherNet[0].struDVRIP.sIpV4;
            deviceInfo.Gateway = m_struNetCfg.struGatewayIpAddr.sIpV4;
            deviceInfo.DVRIPMask = m_struNetCfg.struEtherNet[0].struDVRIPMask.sIpV4;
            deviceInfo.DNS = m_struNetCfg.struDnsServer1IpAddr.sIpV4;
            deviceInfo.AlarmAddr = m_struNetCfg.struAlarmHostIpAddr.sIpV4;
            deviceInfo.AlarmPort = Convert.ToString(m_struNetCfg.wAlarmHostIpPort);
            deviceInfo.HttpPort = Convert.ToString(m_struNetCfg.wHttpPortNo);
            deviceInfo.DVRPort = Convert.ToString(m_struNetCfg.struEtherNet[0].wDVRPort);
            deviceInfo.UseDHCP = (m_struNetCfg.byUseDhcp == 1);
            deviceInfo.PPPOE = (m_struNetCfg.struPPPoE.dwPPPOE == 1);
            if (m_struNetCfg.struPPPoE.dwPPPOE == 1)
            {
                deviceInfo.PPPoEUser = System.Text.Encoding.UTF8.GetString(m_struNetCfg.struPPPoE.sPPPoEUser);
                deviceInfo.PPPoEPassword = m_struNetCfg.struPPPoE.sPPPoEPassword;
            }

            else
            {
                deviceInfo.PPPoEUser = "";
                deviceInfo.PPPoEPassword = "";

            }
            Marshal.FreeHGlobal(ptrNetCfg);
            return true;
        }
        
        #region 抓拍
        /// <summary>
        /// 抓拍
        /// </summary>
        /// <param name="saveFile"></param>
        /// <param name="msg"></param>
        /// <returns></returns>
        public static bool CaptureBMP(int readHandle, string saveFile, out string msg)
        {
            //BMP抓图 Capture a BMP picture
            if (!HCNetSDK.NET_DVR_CapturePicture(readHandle, saveFile))
            {
                var iLastErr = HCNetSDK.NET_DVR_GetLastError();
                msg = "NET_DVR_CapturePicture failed, error code= " + iLastErr;
                return false;
            }
            msg = "NET_DVR_CapturePicture succ and the save";
            return true;
        }
        /// <summary>
        /// 抓拍
        /// </summary>
        /// <param name="saveFile"></param>
        /// <param name="msg"></param>
        /// <returns></returns>
        public static bool CaptureBMP(int readHandle,int port, string saveFile, out string msg)
        {
            int iWidth = 0, iHeight = 0;
            uint iActualSize = 0;

            if (!PlayCtrl.PlayM4_GetPictureSize(port, ref iWidth, ref iHeight))
            {
                var iLastErr = PlayCtrl.PlayM4_GetLastError(port);
                msg = "PlayM4_GetPictureSize failed, error code= " + iLastErr;
                //DebugInfo(str);
                return false;
            }

            uint nBufSize = (uint)(iWidth * iHeight) * 5;

            byte[] pBitmap = new byte[nBufSize];

            if (!PlayCtrl.PlayM4_GetBMP(port, pBitmap, nBufSize, ref iActualSize))
            {
                var iLastErr = PlayCtrl.PlayM4_GetLastError(port);
                msg = "PlayM4_GetBMP failed, error code= " + iLastErr;
                //DebugInfo(str);
                return false;
            }
            FileStream fs = new FileStream(saveFile, FileMode.Create);
            fs.Write(pBitmap, 0, (int)iActualSize);
            fs.Close();
            msg = "PlayM4_GetBMP succ and save!";
            //DebugInfo(str);
            return true;
        }
        /// <summary>
        /// 抓拍
        /// </summary>
        /// <param name="saveFile"></param>
        /// <param name="msg"></param>
        /// <returns></returns>
        public static bool Capture(int userId, int channelIndex, string saveFile, out string msg)
        {
            //int lChannel = this.m_ChannelIndex;

            HCNetSDK.NET_DVR_JPEGPARA lpJpegPara = new HCNetSDK.NET_DVR_JPEGPARA();
            lpJpegPara.wPicQuality = 0; //图像质量 Image quality
            lpJpegPara.wPicSize = 0xff; //抓图分辨率 Picture size: 0xff-Auto(使用当前码流分辨率) 
            //抓图分辨率需要设备支持，更多取值请参考SDK文档

            //var filePath = Application.StartupPath + "\\" + lChannel + "\\Capture";
            //if (System.IO.Directory.Exists(filePath) == false)
            //    System.IO.Directory.CreateDirectory(filePath);

            //JPEG抓图保存成文件 Capture a JPEG picture
            //string sJpegPicFileName = iChannel + "\\" + DateTime.Now.ToString("yyyyMMdd-HHmmss") + ".jpg";

            //if (!HCNetSDK.NET_DVR_CaptureJPEGPicture(userId, channelIndex, ref lpJpegPara, saveFile))
            //{
            //    var iLastErr = HCNetSDK.NET_DVR_GetLastError();
            //    msg = "NET_DVR_CaptureJPEGPicture failed, error code= " + iLastErr;
            //    return false;
            //}
            //msg = "NET_DVR_CaptureJPEGPicture succ and the saved file is " + saveFile;
            //JEPG抓图，数据保存在缓冲区中 Capture a JPEG picture and save in the buffer
            uint iBuffSize = 400000; //缓冲区大小需要不小于一张图片数据的大小 The buffer size should not be less than the picture size
            byte[] byJpegPicBuffer = new byte[iBuffSize];
            uint dwSizeReturned = 0;

            if (!HCNetSDK.NET_DVR_CaptureJPEGPicture_NEW(userId, channelIndex, ref lpJpegPara, byJpegPicBuffer, iBuffSize, ref dwSizeReturned))
            {
                var iLastErr = HCNetSDK.NET_DVR_GetLastError();
                msg = "NET_DVR_CaptureJPEGPicture_NEW failed, error code= " + iLastErr;
                return false;
            }
            msg = "NET_DVR_CaptureJPEGPicture_NEW succ and save the data in buffer to " + saveFile;

            System.IO.File.WriteAllBytes(saveFile, byJpegPicBuffer);
            return true;
        }
        #endregion

        #region 录像
        /// <summary>
        /// 开始录像
        /// </summary>
        /// <param name="saveFile"></param>
        /// <param name="msg"></param>
        /// <returns></returns>
        public static bool BeginRecord(int userId,int channelIndex,int readHandle, string saveFile, out string msg)
        {
            //int m_lRealHandle = -1;
            msg = string.Empty;
            //强制I帧 Make one key frame
            //int lChannel = iChannelNum[(int)iSelIndex]; //通道号 Channel number
            //int lChannel = this.m_ChannelIndex;

            HCNetSDK.NET_DVR_MakeKeyFrame(userId, channelIndex);

            //开始录像 Start recording
            if (!HCNetSDK.NET_DVR_SaveRealData(readHandle, saveFile))
            {
                var iLastErr = HCNetSDK.NET_DVR_GetLastError();
                msg = "NET_DVR_SaveRealData failed, error code= " + iLastErr;
                //AppendText(str);
                return false;
            }
            msg = "NET_DVR_SaveRealData succ!";
            return true;
        }
        /// <summary>
        /// 结束录像
        /// </summary>
        /// <param name="readHandle"></param>
        /// <param name="msg"></param>
        /// <returns></returns>
        public static bool StopRecord(int readHandle, out string msg)
        {
            msg = string.Empty;
            //停止录像 Stop recording
            if (!HCNetSDK.NET_DVR_StopSaveRealData(readHandle))
            {
                var iLastErr = HCNetSDK.NET_DVR_GetLastError();
                msg = "NET_DVR_StopSaveRealData failed, error code= " + iLastErr;
                //AppendText(str);
                return false;
            }
            msg = "NET_DVR_StopSaveRealData succ and the saved!";
            //AppendText(str);
            return true;
        }
        #endregion

        /// <summary>
        /// 注销
        /// </summary>
        /// <param name="userId"></param>
        /// <param name="msg"></param>
        /// <returns></returns>
        public static bool Logout(int userId,out string msg)
        {
            msg = string.Empty;
            var result = HCNetSDK.NET_DVR_Logout(userId);
            if(result == false)
            {
                var iLastErr = HikDVRHelper.GetLastError();
                msg = "NET_DVR_Logout failed, error code= " + iLastErr;
                return result;
            }
            return result;
        }

        /// <summary>
        /// 获取最后异常
        /// </summary>
        /// <returns></returns>
        public static uint GetLastError()
        {
            return HCNetSDK.NET_DVR_GetLastError();
        }

        /// <summary>
        /// 释放资源
        /// </summary>
        public static bool DVR_Cleanup()
        {
            return HCNetSDK.NET_DVR_Cleanup();
        }
    }
}
